Skip to content

feat(web): highlight resolved mentions - #137

Open
jjjhenriksen wants to merge 7 commits into
openclaw:mainfrom
jjjhenriksen:agent/clickclack-semantic-mentions
Open

feat(web): highlight resolved mentions#137
jjjhenriksen wants to merge 7 commits into
openclaw:mainfrom
jjjhenriksen:agent/clickclack-semantic-mentions

Conversation

@jjjhenriksen

@jjjhenriksen jjjhenriksen commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

What changed

  • Highlight resolvable @handle mentions in normal channel and thread messages.
  • Apply the same renderer treatment in embedded channel and thread views, including agent commentary and tool preambles.
  • Load complete workspace-member targets without blocking route/message loading.
  • Refresh mention targets after bot membership changes.
  • Leave mentions inside Markdown links, URL-like paths, and inline/code blocks unchanged.
  • Regenerate the checked-in embedded web assets.

Why

Rendered ClickClack messages showed resolvable workspace handles as ordinary text, making agent handoffs difficult to scan. This is a presentation-only decorator applied after Markdown rendering; storage, delivery, and Markdown parsing are unchanged.

Review findings addressed

The six Codex connector findings are addressed in commit b5be20da03e560784c42fd695819d5546b197a34:

  • member crawling runs in the background;
  • embedded channel/thread views receive complete workspace targets;
  • mutation observation re-highlights edited/rerendered HTML;
  • slash-delimited URL paths are excluded;
  • agent commentary/tool preambles receive the same treatment;
  • bot membership changes refresh the target cache.

Browser proof

After the fixes, Chromium loaded the branch's Vite-served proof page using the real enhanceMentions action and one redacted workspace target (member-29). The live DOM snapshot showed all three rendering surfaces decorated:

ordinary          <mark data-clickclack-mention="true">@member-29</mark>
embedded          <mark data-clickclack-mention="true">@member-29</mark>
agent-commentary  <mark data-clickclack-mention="true">@member-29</mark>

This directly verifies the shared decorator wiring for ordinary, embedded, and agent-commentary content. The existing boundary tests additionally verify that unknown handles, emails, URL paths, links, and code remain untouched.

Validation

  • node --test src/lib/*.test.ts — 20 passed.
  • pnpm typecheck — passed on current head.
  • pnpm fmt:ts:check — passed on current head; the prior CI failure was a formatting issue in mention-people.test.ts, fixed in 65c9638.
  • pnpm --filter @clickclack/web build — passed.
  • Chromium runtime proof — ordinary, embedded, and agent-commentary surfaces each produced a live mention <mark>.

Related to #116.

AI-assisted implementation and review.

@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. labels Jul 31, 2026
@clawsweeper

clawsweeper Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed August 2, 2026, 8:47 AM ET / 12:47 UTC.

ClawSweeper review

What this changes

Adds post-Markdown highlighting for known workspace @handle mentions in normal messages, threads, embedded views, and agent commentary/tool preambles.

Merge readiness

⚠️ Ready for maintainer review - 4 items remain

This PR remains necessary because current main does not implement resolved-mention highlighting. The application-source changes compose with current code, but the checked-in embedded web bundle conflicts with newer generated assets on main, so the branch needs a rebase and regenerated assets before merge.

Priority: P2
Reviewed head: 40d7f9cebb4927bbb00f0beb91bf4c9ea3462605
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) The source patch and stated real-browser proof are credible, but the branch's generated embedded bundle must be rebuilt against current main before it is merge-ready.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (live_output): The PR body provides after-fix Chromium live DOM output for ordinary, embedded, and agent-commentary render surfaces and describes focused boundary tests; after-rebase proof should refresh the generated-client evidence before landing.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (live_output): The PR body provides after-fix Chromium live DOM output for ordinary, embedded, and agent-commentary render surfaces and describes focused boundary tests; after-rebase proof should refresh the generated-client evidence before landing.
Evidence reviewed 5 items Repository policy reviewed: The full repository policy was read; its SQLC generation rule does not apply because this PR changes web rendering and checked-in web assets rather than SQL queries or schema.
Current main lacks the decorator: Current main has no mention-highlight action, range finder, or message-mention styles. Its existing collectMentionPeople helper is local to ChatApp and remains capped at 24 people for current UI behavior.
Source changes compose with main: The three-way merge reports merged results for the changed application source surfaces, including ChatApp, embedded views, message row, preamble, thread panel, and people helper; the feature is not superseded by current main.
Findings None None.
Security None None.

How this fits together

ClickClack renders stored conversation text as Markdown in its main web application and embedded channel/thread views. The proposed decorator receives workspace member targets after rendering and annotates matching visible handles without altering message storage or delivery.

flowchart LR
  A[Workspace member records] --> B[Mention target list]
  C[Rendered Markdown text] --> D[Mention decorator]
  B --> D
  D --> E[Main channel and thread views]
  D --> F[Embedded channel and thread views]
  D --> G[Agent commentary and tool preambles]
Loading

Decision needed

Question Recommendation
Should ClickClack intentionally highlight every resolvable workspace member handle in rendered message history, including members outside the current message window? Approve workspace-wide highlighting: Keep the proposed workspace-wide target set, rebase the source changes, and regenerate the embedded client bundle before the next merge review.

Why: The implementation selects a broader visible-text policy than the existing capped local people list, so maintainer intent is needed in addition to mechanical conflict resolution.

Before merge

  • Resolve merge risk (P1) - The submitted branch is dirty against current main; manually resolving only hashed embedded HTML imports can ship entrypoints that do not match the final generated bundle.
  • Resolve merge risk (P1) - The feature changes rendered historical text for all resolvable workspace members, not only visible authors or direct-conversation participants; that scope should be explicitly accepted before merge.
  • Complete next step (P2) - A maintainer must confirm the workspace-wide display policy, and the contributor must rebase and regenerate the stale embedded bundle before merge.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Patch composition 38 files affected; 13 application/test/style files and 25 generated assets The generated embedded bundle dominates the diff and is the concrete stale-base merge blocker.
Focused coverage 2 new unit-test files They cover known-handle boundaries, case matching, URL/email exclusions, and non-recent workspace targets.

Merge-risk options

Maintainer options:

  1. Rebase and regenerate bundle (recommended)
    Resolve the branch conflict by rebasing on current main, rebuilding checked-in embedded assets, and confirming each HTML entrypoint only imports files present in that refreshed bundle.
  2. Pause pending policy scope
    Do not merge the decorator if maintainers do not want workspace-wide historical mention highlighting as the permanent display contract.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Rebase onto current main, regenerate the checked-in embedded web assets, and verify the resulting HTML entrypoints reference only generated files present in the refreshed bundle.

Technical review

Best possible solution:

Rebase the focused decorator onto current main, regenerate the embedded web assets from that rebased source, and retain the Markdown, URL, and code boundary checks before merging the approved workspace-wide presentation policy.

Do we have a high-confidence way to reproduce the issue?

Yes for the current merge blocker: a source-level three-way merge against current main shows conflicts in both generated embedded HTML entrypoints. The user-visible decorator path is also clear in the PR source, though this read-only review did not run the browser proof itself.

Is this the best way to solve the issue?

No, not as submitted: the decorator is focused, but the branch must be rebased and the embedded bundle regenerated; maintainers must also confirm its workspace-wide targeting policy.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 72931b10f083.

Labels

Label justifications:

  • P2: This is a bounded user-visible web enhancement rather than a broken core workflow.
  • merge-risk: 🚨 compatibility: The PR's checked-in generated web client conflicts with current-main entrypoint assets, and the display change broadens how historical workspace handles are rendered.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body provides after-fix Chromium live DOM output for ordinary, embedded, and agent-commentary render surfaces and describes focused boundary tests; after-rebase proof should refresh the generated-client evidence before landing.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body provides after-fix Chromium live DOM output for ordinary, embedded, and agent-commentary render surfaces and describes focused boundary tests; after-rebase proof should refresh the generated-client evidence before landing.

Evidence

What I checked:

  • Repository policy reviewed: The full repository policy was read; its SQLC generation rule does not apply because this PR changes web rendering and checked-in web assets rather than SQL queries or schema. (AGENTS.md:1, 72931b10f083)
  • Current main lacks the decorator: Current main has no mention-highlight action, range finder, or message-mention styles. Its existing collectMentionPeople helper is local to ChatApp and remains capped at 24 people for current UI behavior. (apps/web/src/ChatApp.svelte:946, 72931b10f083)
  • Source changes compose with main: The three-way merge reports merged results for the changed application source surfaces, including ChatApp, embedded views, message row, preamble, thread panel, and people helper; the feature is not superseded by current main. (apps/web/src/components/messages/MessageRow.svelte:1, 40d7f9cebb49)
  • Generated bundle conflicts with newer main: Current main changed both embedded HTML entrypoints after the PR base, while the PR replaces their hashed bundle references. The three-way merge shows conflicts in both entrypoints, so the submitted generated bundle must be rebuilt after rebasing. (apps/api/internal/webassets/dist/index.html:102, 72931b10f083)
  • Current-main ownership history: Recent history identifies Jacqueline Henriksen on adjacent Markdown/message presentation work and Peter Steinberger on the embedded-client asset and ChatApp path. (apps/web/src/styles/messages.css:867, 72931b10f083)

Likely related people:

  • Jacqueline Henriksen: Recent current-main commit b829398 changes Markdown/message presentation styles adjacent to the proposed mention presentation rule. (role: recent message-rendering contributor; confidence: medium; commits: b829398; files: apps/web/src/styles/messages.css, apps/web/src/components/messages/MessageRow.svelte)
  • Peter Steinberger: Current-main history shows repeated maintenance of checked-in embedded assets and adjacent ChatApp behavior, including 4843afe, e455d43, and 5ef7027. (role: recent embedded-client and ChatApp contributor; confidence: medium; commits: 4843afe, e455d43, 5ef7027; files: apps/api/internal/webassets/dist/index.html, apps/api/internal/webassets/dist/200.html, apps/web/src/ChatApp.svelte)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Rebase the branch and regenerate the checked-in embedded client rather than manually merging hashed asset references.
  • Attach a redacted after-rebase browser or terminal artifact confirming the refreshed embedded entrypoints load the decorator.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (21 earlier review cycles; latest 8 shown)
  • reviewed 2026-08-01T14:52:35.519Z sha b5be20d :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-01T17:33:46.194Z sha b5be20d :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-01T20:14:56.807Z sha b5be20d :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-01T22:58:56.005Z sha 40d7f9c :: needs maintainer review before merge. :: none
  • reviewed 2026-08-02T02:41:53.987Z sha 40d7f9c :: needs maintainer review before merge. :: none
  • reviewed 2026-08-02T05:08:47.401Z sha 40d7f9c :: needs maintainer review before merge. :: none
  • reviewed 2026-08-02T07:13:32.219Z sha 40d7f9c :: needs maintainer review before merge. :: none
  • reviewed 2026-08-02T10:21:35.109Z sha 40d7f9c :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot removed the proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. label Jul 31, 2026
@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. labels Jul 31, 2026
@jjjhenriksen
jjjhenriksen marked this pull request as ready for review August 1, 2026 02:25

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1acfbb95ed

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +919 to +927
do {
const page = await listWorkspaceMembersPage({
workspaceID,
cursor,
limit: 100,
});
members.push(...page.members.map((member) => member.user));
cursor = page.has_more ? page.next_cursor : undefined;
} while (cursor);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid blocking route loading on every member page

When a workspace has more than 100 members, this loop issues one request per page serially, and applyRoute awaits the entire loadWorkspaceMembers call before resolving the route target and loading its messages. Opening or switching a large workspace can therefore leave the conversation blocked behind dozens or hundreds of member-list requests; load these targets in the background or resolve only the handles needed for visible messages.

Useful? React with 👍 / 👎.

Comment on lines +928 to +929
if (serial !== workspaceMembersLoadSerial || workspaceID !== selectedWorkspaceID) return;
workspaceMemberUsers = members;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refresh mention targets after bot membership changes

This assignment creates a snapshot that is only refreshed when the workspace changes. The existing bot.deleted and bot.membership_removed realtime handlers reload direct conversations, moderation data, and commands but never this list, so a removed bot's old handle remains highlighted as resolvable—and a newly added or replacement bot is absent—until the user reloads or switches workspaces.

Useful? React with 👍 / 👎.

Comment on lines +89 to +93
return {
update(nextPeople: User[] = []) {
targets = mentionTargets(nextPeople);
renderMentionHighlights(node, targets);
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Re-run highlighting when rendered message HTML changes

The action updates only when mentionPeople changes, not when the element's {@html markdown(message.body)} content changes. For example, a realtime edit of a reply in the currently open thread replaces the reply HTML while the workspace people array remains unchanged, leaving mentions in the edited body unhighlighted until some unrelated people-list update or remount; observe child mutations or pass the body/version into the action.

Useful? React with 👍 / 👎.

Comment on lines +33 to +37
function mentionIsInsideURL(text: string, start: number): boolean {
const tokenStart =
Math.max(text.lastIndexOf(" ", start - 1), text.lastIndexOf("\n", start - 1)) + 1;
const prefix = text.slice(tokenStart, start);
return /^(?:www\.[^\s/]+|[A-Za-z][A-Za-z0-9+.-]*:\/\/[^\s/]+)\//u.test(prefix);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude bare URL paths from mention matches

The URL check only recognizes prefixes beginning with www. or a URI scheme. Plain URL-like paths such as /users/@alice and docs/path/@alice?tab=1 therefore highlight @alice, despite the feature's intended exclusion of URL paths; detect slash-delimited path tokens as well as fully qualified URLs.

Useful? React with 👍 / 👎.

<MessageList
{messages}
selectedChannel={channel}
{mentionPeople}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve mentions against all members in embedded views

The embedded channel passes a mentionPeople list derived only from the authors in the currently loaded message window plus the current user, capped at 24 entries; EmbedThreadView similarly uses only conversation members and loaded authors. Consequently, a valid workspace mention remains plain whenever its target has not authored one of those loaded messages, so embedded views do not consistently provide the resolved-mention treatment added here; fetch or otherwise resolve workspace targets for embeds as well.

Useful? React with 👍 / 👎.

{:else}
<QuoteBlock {message} onJump={onJumpToQuote} />
<div class="markdown" use:enhanceMarkdown>{@html markdown(message.body)}</div>
<div class="markdown" use:enhanceMarkdown use:enhanceMentions={mentionPeople}>{@html markdown(message.body)}</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Highlight mentions in agent commentary preambles

The new action is attached only in the ordinary-message branch, while coalesced agent_commentary rows take the earlier PreambleBlock branch and render their commentary Markdown with only enhanceMarkdown. A bot message such as Handing this to @alice therefore remains unhighlighted when it is displayed as a preamble, which omits the semantic treatment from the agent-handoff content this feature is intended to make scannable; pass the mention targets into PreambleBlock and enhance its commentary bodies too.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. and removed proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Aug 1, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Aug 1, 2026
@clawsweeper clawsweeper Bot added the rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. label Aug 1, 2026
@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant